package top.yekongle.feature.java8.stream;

import org.junit.Ignore;
import org.junit.Test;
import top.yekongle.feature.java8.lambda.Employee;
import top.yekongle.feature.java8.lambda.Employee.Status;

import java.util.*;
import java.util.function.Function;
import java.util.function.ToDoubleFunction;
import java.util.stream.Collectors;

/**
 * 终止操作
 *
 * 查找与匹配
 * allMatch - 检查是否匹配所有元素
 * anyMatch - 检查是否至少匹配一个元素
 * noneMatch - 检查是否没有匹配所有元素
 * findFirst - 返回第一个元素
 * findAny - 返回当前流中的任意元素
 * count - 返回流中的元素的总个数
 * max - 返回流中最大值
 * min - 返回流中最小值
 */
@Ignore
public class TestStream3 {

    List<Employee> employees = Arrays.asList(
            new Employee("张三", 18, 5555.55, Status.FREE ),
            new Employee("李四", 19, 6666.66, Status.BUSY),
            new Employee("王五", 40, 7777.77, Status.VOCATION),
            new Employee("赵六", 45, 7777.77, Status.FREE),
            new Employee("孙七", 60, 7777.77, Status.VOCATION)
    );
//    List<Employee> employees = null;


    
    public void test1() {
        // allMatch - 检查是否匹配所有元素
        boolean result = employees.stream().allMatch((e) -> e.getStatus().equals(Status.FREE));
        System.out.println(result);

        // anyMatch - 检查是否至少匹配一个元素
        boolean result1 = employees.stream().anyMatch((e) -> e.getStatus().equals(Status.FREE));
        System.out.println(result1);

        // noneMatch - 检查是否没有匹配所有元素
        boolean result2 = employees.stream().noneMatch((e) -> e.getStatus().equals(Status.FREE));
        System.out.println(result2);

        // findFirst - 返回第一个元素
        Optional<Employee> op = employees.stream()
                .sorted((e1, e2) -> -Double.compare(e1.getSalary(), e2.getSalary()))
                .findFirst();

       System.out.println(op.get().getName());


       // findAny - 返回当前流中的任意元素
       Optional<Employee> op2 = employees.stream().filter((e) -> e.getStatus().equals(Status.FREE)).findAny();
       System.out.println(op2.get().getName());
    }

    
    public void test2() {

        // count - 返回流中的元素的总个数
        Long count = employees.stream().count();
        System.out.println("Count:" + count);

        // max - 返回流中最大值
        Optional<Employee> op1 = employees.stream().max((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()));
        System.out.println("Max value:" + op1.get().getSalary());

        // min - 返回流中最小值
        Optional<Employee> op2 = employees.stream().min((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()));
        System.out.println("Min value:" + op2.get().getSalary());

        Optional<Double> op3 = employees.stream().map(Employee::getSalary).min(Double::compare);
        System.out.println(op3.get());

    }


    
//        规约：
//        reduce(T identity, BinaryOperator) / reduce(BinaryOperator)
//        可以将流中元素反复结合起来，得到一个值
     
    
    public void test3() {
        List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
        Integer sum = list.stream().reduce(0, (x, y) -> x + y);
        System.out.println("Sum: " + sum);

        Employee ee = new Employee("张三", 18, 5555.55, Status.FREE);
//        employees.stream().map()
    }

    
//        收集
//        collect - 将流转换为其他方式。接收一个 Collector 接口的实现，用于给 Stream 中元素汇总的方法
     
    
    public void test4() {
        List<String> list = employees.stream()
                .map(Employee::getName)
                .collect(Collectors.toList());

        //list.forEach(System.out::println);

        Set<String> set = employees.stream().map(Employee::getName).collect(Collectors.toSet());
        //set.forEach(System.out::println);

        HashSet<String> hs = employees.stream()
                .map(Employee::getName)
                .collect(Collectors.toCollection(HashSet::new));
        hs.forEach(System.out::println);
    }

    
    public void test5() {
        // 总数
        Long count = employees.stream().collect(Collectors.counting());
        //System.out.println(count);

        // 平均值
        Double avg = employees.stream()
                .collect(Collectors.averagingDouble(Employee::getSalary));
        //System.out.println("Avg: " + avg);

        // 总和
        ToDoubleFunction<Employee> fun3 = Employee::getSalary;
        Double sum = employees.stream().collect(Collectors.summingDouble(fun3));
        System.out.println("Sum:" + sum);

        // 最大值
        Optional<Employee> maxEE = employees.stream().collect(Collectors.maxBy((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())));
        System.out.println("Max: " + maxEE.get());

        // 最小值
        Optional<Double> minSalary = employees.stream().map(Employee::getSalary).collect(Collectors.minBy(Double::compare));
        System.out.println("Min: " + minSalary.get());
    }


    // 分组
    
    public void test6() {
        // 分组
        Map<Status, List<Employee>> map = employees.stream().collect(Collectors.groupingBy(Employee::getStatus));
        System.out.println(map);

        // 多级分组
        Map<Status, Map<String, List<Employee>>> map1 = employees.stream().collect(Collectors.groupingBy(Employee::getStatus, Collectors.groupingBy((e) -> {
            if (e.getAge() < 35) {
                return "青年";
            } else if (e.getAge() < 50) {
                return "中年";
            } else {
                return "老年";
            }
        })));

        System.out.println(map1);
    }

    // 分区: 满足条件的一个区，不满足条件的一个区
    
    public void test7() {
        Map<Boolean, List<Employee>> map = employees.stream().collect(Collectors.partitioningBy((e) -> e.getSalary() > 8000));
        System.out.println(map);

    }

    
    public void test8() {
        DoubleSummaryStatistics dss = employees.stream().collect(Collectors.summarizingDouble(Employee::getSalary));
        System.out.println(dss.getMax());
        System.out.println(dss.getMin());
        System.out.println(dss.getAverage());
    }

    
    public void test9() {
        String str = employees.stream().map(Employee::getName).collect(Collectors.joining(","));
        System.out.println("Name: " + str);
    }
}
